﻿using Rw.Core.Common.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace WH.Common.Helper
{
    public class SecurityHelper
    {
        private const string KEY = "r3bDtQ0iw1Xq58fdh4+ZTOLT4TRH3iGYvHZhWjlZ1h4=";
        private const string IV = "Ex8aYDDznGudKhXZkf+ujQ==";

        /// <summary>
        /// 前端密文到存储密文
        /// </summary>
        /// <param name="encryptedBytes"></param>
        /// <returns></returns>
        public static string? FrontendToStorage(string decStr)
        {
            if (string.IsNullOrWhiteSpace(decStr))
            {
                return default;
            }

            var plaintext = FrontendAesDecrypt(decStr, KEY, IV);
            plaintext ??= decStr;

            try
            {
                var ciphertext = MysqlAesHelper.Encrypt(plaintext);
                return ciphertext;
            }
            catch
            {
                return plaintext;
            }
        }
        /// <summary>
        /// 前端密文到明文
        /// </summary>
        /// <param name="encryptedBytes"></param>
        /// <returns></returns>
        public static string? FrontendStorage(string decStr)
        {
            if (string.IsNullOrWhiteSpace(decStr))
            {
                return default;
            }

            var plaintext = FrontendAesDecrypt(decStr, KEY, IV);
            plaintext ??= decStr;
            return plaintext;
        }

        /// <summary>
        /// 存储密文到前端密文
        /// </summary>
        /// <param name="decStr"></param>
        /// <returns></returns>
        public static string? StorageToFrontend(string decStr)
        {
            if (string.IsNullOrWhiteSpace(decStr))
            {
                return default;
            }

            string? plaintext;
            try
            {
                plaintext = MysqlAesHelper.Decrypt(decStr);
            }
            catch
            {
                plaintext = decStr;
            }

            if (string.IsNullOrWhiteSpace(decStr))
            {
                return default;
            }

            var ciphertext = FrontendAesEncrypt(plaintext, KEY, IV);
            return ciphertext;
        }


        #region AES加密

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="encryptedBytes">待加密的字节数组</param>
        /// <returns></returns>
        public static string FrontendAesEncrypt(string decStr)
        {
            return FrontendAesEncrypt(decStr, KEY, IV);
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="encryptedBytes">待加密的字节数组</param>
        /// <param name="keyBytes">加密密钥字节数组</param>
        /// <param name="ivBytes">IV初始化向量字节数组</param>
        /// <returns></returns>
        public static string FrontendAesEncrypt(string decStr, string key, string iv)
        {
            try
            {
                var encryptedBytes = Encoding.UTF8.GetBytes(decStr);
                var keyBytes = Convert.FromBase64String(key);
                var ivBytes = Convert.FromBase64String(iv);
                var result = FrontendEncryptToAesBytes(encryptedBytes, keyBytes, ivBytes);
                return Convert.ToBase64String(result);
            }
            catch (Exception)
            {
                return "";
            }
        }

        /// <summary>
        /// AES加密
        /// Add by 成长的小猪（Jason.Song） on 2018/10/26
        /// </summary>
        /// <param name="encryptedBytes">待加密的字节数组</param>
        /// <param name="keyBytes">加密密钥字节数组</param>
        /// <param name="ivBytes">IV初始化向量字节数组</param>
        /// <param name="cipher">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <returns></returns>
        public static byte[] FrontendEncryptToAesBytes(byte[] encryptedBytes, byte[] keyBytes, byte[] ivBytes,
            CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            if (encryptedBytes == null || encryptedBytes.Length <= 0)
            {
                throw new ArgumentNullException(nameof(encryptedBytes));
            }

            if (keyBytes == null || keyBytes.Length <= 0)
            {
                throw new ArgumentNullException(nameof(keyBytes));
            }

            if (ivBytes == null || ivBytes.Length <= 0)
            {
                throw new ArgumentNullException(nameof(ivBytes));
            }

            var des = new AesCryptoServiceProvider
            {
                Key = keyBytes,
                IV = ivBytes,
                Mode = cipher,
                Padding = padding
            };
            var outputBytes = des.CreateEncryptor().TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return outputBytes;
        }

        #endregion AES加密

        #region AES解密

        /// <summary>
        /// AES解密
        /// Add by 成长的小猪（Jason.Song） on 2018/10/26
        /// </summary>
        /// <param name="decryptedBytes">待解密的字节数组</param>
        /// <param name="keyBytes">解密密钥字节数组</param>
        /// <param name="ivBytes">IV初始化向量字节数组</param>
        /// <param name="cipher">运算模式</param>
        /// <param name="padding">填充模式</param>
        /// <returns></returns>
        public static byte[] FrontendDecryptByAesBytes(byte[] decryptedBytes, byte[] keyBytes, byte[] ivBytes,
            CipherMode cipher = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
        {
            if (decryptedBytes == null || decryptedBytes.Length <= 0)
            {
                throw new ArgumentNullException(nameof(decryptedBytes));
            }

            if (keyBytes == null || keyBytes.Length <= 0)
            {
                throw new ArgumentNullException(nameof(keyBytes));
            }

            if (ivBytes == null || ivBytes.Length <= 0)
            {
                throw new ArgumentNullException(nameof(ivBytes));
            }

            var aes = new AesCryptoServiceProvider
            {
                Key = keyBytes,
                IV = ivBytes,
                Mode = cipher,
                Padding = padding
            };
            var outputBytes = aes.CreateDecryptor().TransformFinalBlock(decryptedBytes, 0, decryptedBytes.Length);
            return outputBytes;
        }

        /// <summary>
        /// AES 算法解密(CBC模式) 先base64解码再解密，返回明文
        /// </summary>
        /// <param name="DecryptStr">密文</param>
        /// <param name="Key">密钥</param>
        /// <param name="iv">IV初始化向量字节数组</param>
        /// <returns>明文</returns>
        public static string FrontendAesDecrypt(string decStr, string key, string iv)
        {
            try
            {
                var decryptArray = Convert.FromBase64String(decStr);
                var keyArray = Convert.FromBase64String(key);
                var ivs = Convert.FromBase64String(iv);

                var rDel = new RijndaelManaged
                {
                    Key = keyArray,
                    Mode = CipherMode.CBC,
                    Padding = PaddingMode.PKCS7,
                    IV = ivs
                };

                var cTransform = rDel.CreateDecryptor();
                var result = cTransform.TransformFinalBlock(decryptArray, 0, decryptArray.Length);

                return Encoding.UTF8.GetString(result);
            }
            catch (Exception)
            {
                return "";
            }
        }


        /// <summary>
        /// AES 算法解密(CBC模式) 先base64解码再解密，返回明文
        /// </summary>
        /// <param name="DecryptStr">密文</param>
        /// <returns>明文</returns>
        public static string FrontendAesDecrypt(string decStr)
        {
            return FrontendAesDecrypt(decStr, KEY, IV);
        }
        #endregion AES解密

    }
}
